package com.wyx.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wyx.annotation.MethodEventDescription;
import com.wyx.easyExcel.easyExcelHandler.MergeHandler;
import com.wyx.easyExcel.easyExcelHandler.ExportAllFileCellColorHandler;
import com.wyx.easyExcel.easyExcelHandler.ExportAllFileCellColorHandler2;
import com.wyx.easyExcel.easyExcelListen.BaseSmokeInfoListener;
import com.wyx.easyExcel.easyExcelPojo.*;

import com.wyx.easyExcel.easyExcelPojo.putTactics.AnticipatedOrderData;
import com.wyx.easyExcel.easyExcelPojo.putTactics.GearExtendSelection;
import com.wyx.easyExcel.easyExcelPojo.putTactics.PriceSelection;
import com.wyx.easyExcel.easyExcelPojo.putTactics.WeeklySupplyStrategyData;
import com.wyx.easyExcel.easyExcelRead.WeeklySupplyStrategyRead;
import com.wyx.easyExcel.easyExcelWrite.WeeklySupplyStrategyDataTempleWrite;
import com.wyx.exception.PicNullException;
import com.wyx.exception.SmokeException;
import com.wyx.httpService.shanxitobaccoService.MerchantRetailInteractionService;
import com.wyx.httpService.shanxitobaccoService.impl.OrderShanxiTobaccoCrawlerServiceImpl;
import com.wyx.httpService.shanxitobaccoService.impl.SmokeInfoShanxiTobaccoCrawlerServiceImpl;
import com.wyx.mapper.SmokeInfoLogMapper;
import com.wyx.mapper.SmokeMapper;
import com.wyx.pojo.Pic;
import com.wyx.pojo.Smoke;
import com.wyx.pojo.SmokeInfoLog;
import com.wyx.pojo.httpSmokeBean.shanxitobaccobean.ThreePublishBaseInfo;
import com.wyx.pojo.httpSmokeBean.shanxitobaccobean.ThreePublishRes;
import com.wyx.pojo.templateConfig.*;
import com.wyx.pojo.constant.ConfigRead;
import com.wyx.pojo.dto.SmokeDto;
import com.wyx.pojo.httpSmokeBean.shanxitobaccobean.response.*;
import com.wyx.pojo.ProductBeanResult;
import com.wyx.pojo.result.CODE;
import com.wyx.pojo.result.CheckInfo;
import com.wyx.pojo.result.CheckInfoRes;
import com.wyx.pojo.result.SmokeNews;
import com.wyx.service.SmokeInfoLogService;
import com.wyx.utils.CompareRes;
import com.wyx.service.PicService;
import com.wyx.service.SmokeService;
import com.wyx.utils.ObjComparators;
import com.wyx.utils.ObjCompareFunction;
import com.wyx.utils.commonUtil.*;
import com.wyx.utils.threadSave.StoreInfoHolder;
import com.wyx.utils.threadSave.ThreadUserInfo;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.IndexedColors;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.Charset;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.IntStream;

/**
 * @author 吴宇~
 * @motto 我亦无他，唯手熟尔。
 * @edition jdk1.8
 * @reflection 0-1 喧闹任其喧闹，自由我自为之，我自风情万种，与世无争。
 * @date 2024/04/04/20:48
 * @target 心若有所向往，何惧道阻且长
 */

/**
 * 这个实现和SmokeInfoService 的区别是  。
 * 这个实现重在数据库和业务上的操作 ，那个是实现重在封装http请求的操作
 */
@Service
@Slf4j
public class SmokeServiceImpl extends ServiceImpl<SmokeMapper, Smoke> implements SmokeService {
    @Autowired
    private SmokeInfoShanxiTobaccoCrawlerServiceImpl smokeInfoShanxiTobaccoCrawlerService;
    @Autowired
    private SmokeService smokeService;
    @Autowired
    private SmokeMapper smokeMapper;
    @Autowired
    private OrderShanxiTobaccoCrawlerServiceImpl orderShanxiTobaccoCrawlerService;
    @Autowired
    private SmokeInfoLogMapper smokeInfoLogMapper;
    @Autowired
    private SmokeInfoLogService smokeInfoLogService;

    @Autowired
    private SmokeAnticipatedOrder smokeAnticipatedOrder;

    @Autowired
    private PicService picService;

    //这些东西存储在redis 里面合适吧
    @Autowired
    private ConfigRead configRead;

    @Autowired
    private SmokeListTemplate1Config smokeListTemplate1Config;
    @Autowired
    private SmokeListTemplate2Config smokeListTemplate2Config;
    @Autowired
    private SmokeListTemplate2_1Config smokeListTemplate2_1Config;
    @Autowired
    private SmokeOrderTemplate1Config smokeOrderTemplate1Config;
    @Autowired
    private SmokeOrderTemplate2Config smokeOrderTemplate2Config;
    @Autowired
    private MerchantRetailInteractionService merchantRetailInteractionService;


    /**
     * @param csvByte 传入csv文件的byte数组
     * @return 返回经过转换的byte数组
     */
    @Override
    public byte[] getOrderPictureByCSVOrderFile(byte[] csvByte) throws FileNotFoundException {
        InputStream inputStream = new ByteArrayInputStream(csvByte);
//        读取csv文件 获取list集合
        List<CSVSmokeInfo> baseSmokeInfos = EasyExcel
                .read(inputStream,
                        CSVSmokeInfo.class,
                        new BaseSmokeInfoListener())
                .charset(Charset.forName("GBK"))
                .excelType(ExcelTypeEnum.CSV)
                .sheet()
                .doReadSync();
        try {
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Map<String, Object> excelListMap = smokeService.getExcelListMap(baseSmokeInfos);
//        获取map数据
        Map<String, Object> smokeSingleComputeInfoMap = getDataMap((List<ExcelSmokeInfo>) (excelListMap.get("baseInfo")));
//        写数据到excel中
        byte[] excelByte = write(excelListMap, smokeSingleComputeInfoMap, smokeOrderTemplate1Config.getFileByte());

        return smokeService.excelToPic(excelByte);
    }

    //得到最新订单所需要的list 已map的方式 呈现
    @MethodEventDescription(event = "get all excel list Map")
    @Override
    public Map<String, Object> getExcelListMap(List<CSVSmokeInfo> baseSmokeInfos) {
        HashMap<String, Object> excelListMap = new HashMap<>();
        List<ExcelSmokeInfo> excelSmokeInfo = smokeService.getBaseExcelSmokeInfo(baseSmokeInfos);
        List<SmokeDto> allSmokeBatchInfo = new ArrayList<>();
        List<SmokeDto> addSmokeDtos = new ArrayList<>();
        List<SmokeDto> deleteSmokeDtos = new ArrayList<>();
        List<SmokeDto> updateSmokeDtos = new ArrayList<>();
        String latestSerialId = smokeMapper.getLatestSerialId();
        //如果序列号为空 一般不会
        if (latestSerialId == null) {
            // 说明原本没有数据
            throw new RuntimeException("序列号异常");
        }
        List<String> allSerialDesc = smokeMapper.getAllSerialDesc();
        do {
            List<SmokeDto> allSmoke = smokeMapper.getAllSmokeBySerial(latestSerialId);
            allSmokeBatchInfo.addAll(allSmoke);
            latestSerialId = ListUtil.getPreSerialId(allSerialDesc, latestSerialId);
            if (latestSerialId == null) {
                //如果没有就说明 没有更多的信息了。
                break;
            }
        } while (allSmokeBatchInfo.size() < 10);
        for (SmokeDto smoke : allSmokeBatchInfo) {
            char dataStatus = smoke.getDataStatus();
            if (dataStatus == '1') {
                String orgIsCigar = smoke.getOrgIsCigar();
                String orgIsAbnormity = smoke.getOrgIsAbnormity();

                String isCigar = "1".equals(orgIsCigar) ? "是" : "0".equals(orgIsCigar) ? "不是" : "未知";
                String isAbnormity = "1".equals(orgIsAbnormity) ? "是" : "0".equals(orgIsAbnormity) ? "不是" : "未知";

                String remarks = String.format("%s|上架了 %s|批发价: %s|建议售卖价: %s|%s 异型|%s 雪茄|%s",
                        DateUtil.formatTime(smoke.getCreateTime()),
                        smoke.getProductName(),
                        smoke.getWholeSalePrice(),
                        smoke.getRetailPrice(),
                        isAbnormity,
                        isCigar,
                        smoke.getPriceTypeCodeName());
                String s = StringUtils.formatString(remarks, new int[]{22, 23, 18, 20, 7, 10, 5});
                SmokeDto smokeDto = new SmokeDto();
                smokeDto.setChangeDesc(s);
                if (smoke.getPicAddress() != null) {
                    smokeDto.setPicFile(FileUtil.getResourceFile(configRead.getSmokePicPath() + smoke.getPicAddress() + "." + smoke.getImageType()));
                }
                addSmokeDtos.add(smokeDto);
            } else if (dataStatus == '2') {
                //下架
                String format = String.format("%s|下架了 %s",
                        DateUtil.formatTime(smoke.getCreateTime()),
                        smoke.getProductName());
                String desc = StringUtils.formatString(format, new int[]{22, 20});
                SmokeDto smokeDto = new SmokeDto();
                smokeDto.setChangeDesc(desc);
                if (smoke.getPicAddress() != null) {
                    smokeDto.setPicFile(FileUtil.getResourceFile(configRead.getSmokePicPath() + smoke.getPicAddress() + "." + smoke.getImageType()));
                }
                deleteSmokeDtos.add(smokeDto);
            } else if (dataStatus == '3') {
                String format = String.format("%s|%s 发生更新|更新有：..更新为..", smoke.getCreateTime(), smoke.getProductName());
                SmokeDto smokeDto = new SmokeDto();
                String remark = StringUtils.formatString(format, new int[]{22, 22, 30});
                smokeDto.setChangeDesc(remark);
                if (smoke.getPicAddress() != null) {
                    smokeDto.setPicFile(FileUtil.getResourceFile(configRead.getSmokePicPath() + smoke.getPicAddress() + "." + smoke.getImageType()));
                }
                updateSmokeDtos.add(smokeDto);
            }
        }
        if (addSmokeDtos.size() == 0) {
            SmokeDto smokeDto = new SmokeDto();
            smokeDto.setChangeDesc("无上架");
            addSmokeDtos.add(smokeDto);
        }

        if (deleteSmokeDtos.size() == 0) {
            SmokeDto smokeDto = new SmokeDto();
            smokeDto.setChangeDesc("无下架");
            deleteSmokeDtos.add(smokeDto);
        }

        if (updateSmokeDtos.size() == 0) {
            SmokeDto smokeDto = new SmokeDto();
            smokeDto.setChangeDesc("无修改");
            updateSmokeDtos.add(smokeDto);
        }
        excelListMap.put("baseInfo", excelSmokeInfo);
        excelListMap.put("addSmokeRemarks", addSmokeDtos);
        excelListMap.put("deleteSmokeRemarks", deleteSmokeDtos);
        excelListMap.put("updateSmokeRemarks", updateSmokeDtos);
        return excelListMap;
    }

    // 得到周货源投放策略的信息的图片
    @Override
    public byte[] getWeeklySupplyPlacementStrategyInformation() {
//        1. 获取模板数据
//          1.1 首先点击更多
        ThreePublishRes threePublishRes = merchantRetailInteractionService.threeOpenness_more();
//          1.2 然后选择需要的数据进行下载，
        List<ThreePublishBaseInfo> rows = threePublishRes.getRows();
        String targetHref = null;
        for (ThreePublishBaseInfo row : rows) {
            Elements elements = Jsoup.parse(row.getRemark()).select("a[href]");
            if (elements.size() == 0) {
                continue;
            }
            Element element = elements.get(0);
            String fileName = element.text();
            String regex = "\\d{4}\\.([1-9]|1[0-2])\\.([1-9]|[12][0-9]|3[01])-" + // 开始日期部分
                    "([1-9]|1[0-2])\\.([1-9]|[12][0-9]|3[01])" + // 结束日期部分
                    "周货源投放策略\\(太原\\)\\.xls[x]?"; // 文件名后缀
            Matcher matcher = Pattern.compile(regex).matcher(fileName);
            if (matcher.matches()) {
                targetHref = element.attr("href");
                log.debug("选择的数据为: {}", fileName);
                break;
            }
        }
        byte[] bytes = merchantRetailInteractionService.downPublicInformation(targetHref);
//        2. 解析数据  最终得到一个对象，包含全部的数据
        WeeklySupplyStrategyData weeklySupplyStrategyData = WeeklySupplyStrategyRead.process(bytes);

//            2.1 处理这个数据，将不投放的卷烟去掉
        revisedData(weeklySupplyStrategyData);
//        3. 将数据根据模板写入  这部分应该也是easyExcel 来处理的事情。但是需要使用继续查询数据库的数据，所以在这儿查好传过去
        List<String> encodeList = new ArrayList<>();
        for (AnticipatedOrderData anticipatedOrderData : weeklySupplyStrategyData.getGearSelection().getList()) {
            encodeList.add(anticipatedOrderData.getProductEncoding());
        }

        for (PriceSelection selection : weeklySupplyStrategyData.getPriceSelection()) {
            for (AnticipatedOrderData anticipatedOrderData : selection.getList()) {
                encodeList.add(anticipatedOrderData.getProductEncoding());
            }
        }
        for (GearExtendSelection gearExtendSelection : weeklySupplyStrategyData.getGearExtendSelectionList()) {
            encodeList.add(gearExtendSelection.getList().get(0).getProductEncoding());
        }
        List<Smoke> allSmokeByProductCode = smokeMapper.getAllSmokeByProductCode(encodeList);
        Map<String, Smoke> dbInfo = allSmokeByProductCode.stream().collect(Collectors.toMap(Smoke::getProductCode, smoke -> smoke));

        byte[] res = WeeklySupplyStrategyDataTempleWrite.process(new ByteArrayInputStream(smokeAnticipatedOrder.getTemplateFileByte()), ExcelTypeEnum.XLS, weeklySupplyStrategyData, dbInfo, smokeAnticipatedOrder);
//        4. 将excel转换为图片输出
        return smokeService.excelToPic(res);
    }

    /**
     * 下载图片，得到最新的订单的图片byte数组
     *
     * @return 经过转换的订单的 byte数组
     */
    @Override
    @MethodEventDescription(event = "use {{#1}} template get latest order pic", isFillMethodArg = true, isShowAllArg = true, isShowAllEventCost = true)
    public byte[] getLastOrderPic(String template) throws FileNotFoundException {
        String currentQuarterFirstDay = DateUtil.queryCurrentQuarterFirstDay();
        String endDay = DateUtil.queryCurrentDay();
        String startDay = currentQuarterFirstDay.equals(endDay) ? DateUtil.getLastQuarterFirstDay() : currentQuarterFirstDay;
        OrderInfo orderInfo = orderShanxiTobaccoCrawlerService.selectOrderListByDate(startDay, endDay);
        if (orderInfo.getRows().size() == 0 || orderInfo.getRows().get(0) == null) {
            System.out.println("未查询到对应的订单信息");
        }
        Bill bill = orderInfo.getRows().get(0);
        return smokeService.getOrderPictureByCSVOrderFile(orderShanxiTobaccoCrawlerService.selectOrderDetailCSVFileByOrderId(bill.getBill_uuid()));
    }

    /**
     * 返回所有烟的信息的图片
     *
     * @return 返回图片的byte数组
     */
    @Override
    @MethodEventDescription(event = "use {{#1}} template get smoke list pic", isFillMethodArg = true, isShowAllEventCost = true)
    public byte[] getSmokeListPicByte(String templateType) {
        List<String> smokeIds = new ArrayList<>();
        List<SmokeDto> smokeDtos = new ArrayList<>();
        List<Smoke> collectSmoke = smokeService.list().stream()
                .peek(smoke -> smokeIds.add(smoke.getId()))
                .map(smoke -> {
                    if (smoke.getOrgIsCigar() == null) {
                        log.info("{} 不确定雪茄类型", smoke.getProductName());
                        throw new RuntimeException("smoke Exception");
                    }
                    smoke.setOrgIsCigar("1".equals(smoke.getOrgIsCigar()) ? "是" : "否");
                    smoke.setOrgIsAbnormity(smoke.getOrgIsAbnormity().equals("1") ? "是" : "否");
                    return smoke;
                })
                .sorted((o1, o2) -> (int) (100 * (Double.parseDouble(o1.getWholeSalePrice()) - Double.parseDouble(o2.getWholeSalePrice()))))
                .collect(Collectors.toList());


        Map<String, Pic> collectPic = picService.list(new LambdaQueryWrapper<Pic>().in(Pic::getObjId, smokeIds).select(Pic::getId, Pic::getObjId, Pic::getImageType, Pic::getPicAddress)).stream().collect(Collectors.toMap(Pic::getObjId, pic -> pic));

        collectSmoke.forEach(smoke -> {
            SmokeDto smokeDto = new SmokeDto();
            BeanUtil.copyProperties(smoke, smokeDto);
            Pic pic = collectPic.get(smokeDto.getId());
            if (pic != null) {
                smokeDto.setPicFile(FileUtil.getResourceFile(configRead.getSmokePicPath() + pic.getPicAddress() + "." + pic.getImageType()));
            }
            smokeDtos.add(smokeDto);
        });

        byte[] bytes;

        String listTemplate1Name = FileUtil.getFileNameExcludeSuffix(smokeListTemplate1Config.getFileName());

        String listTemplate2Name = FileUtil.getFileNameExcludeSuffix(smokeListTemplate2Config.getFileName());

        String listTemplate2_1Name = FileUtil.getFileNameExcludeSuffix(smokeListTemplate2_1Config.getFileName()
//                configRead.getListTemplate2_1FileName()
        );

        if (templateType.equals(listTemplate2Name) || templateType.equals(listTemplate2_1Name)) {
            bytes = smokeService.writeListWithListTemplate2(smokeDtos, templateType);
        } else if (templateType.equals(listTemplate1Name)) {
            bytes = smokeService.writeListWithListTemplate1(smokeDtos, templateType);
        } else {
            System.out.println("没有找到对应模板: " + templateType);
            return configRead.getTempNullJpg();
        }
        byte[] resBytes = null;
        resBytes = smokeService.excelToPic(bytes);
        return resBytes;

    }

    /**
     * 根据当前数据进行一个计算 转换
     * double的运算统一使用
     * BigDecimal a = new BigDecimal("10.5");
     * BigDecimal b = new BigDecimal("2.5");
     * BigDecimal c = a.add(b); // 加法运算
     * BigDecimal d = a.subtract(b); // 减法运算
     * BigDecimal e = a.multiply(b); // 乘法运算
     * BigDecimal f = a.divide(b); // 除法运算
     * BigDecimal g = a.remainder(b); // 取余运算
     *
     * @param smokeInfos 烟的基本信息
     * @return 返回经过计算后的map集合
     * <p>
     * //需要四舍五入
     * smokeInfo.setRealBarRate(new DecimalFormat("0.00%").format(barProfit.divide(realSalePriceDec, 4, RoundingMode.HALF_UP)));
     */
    @Override
    @MethodEventDescription(event = "compute order scattered")
    public Map<String, Object> getDataMap(List<ExcelSmokeInfo> smokeInfos) {
        int totalNum = 0;
        BigDecimal totalAmount = new BigDecimal("0");
        BigDecimal estimateTotalPrice = new BigDecimal("0");
        BigDecimal suggestSellProfit = new BigDecimal("0");
        BigDecimal averagePrice = new BigDecimal("0");
//        常规数量
        int normalSmoke = 0;
//        异型数量
        int abnormalSmoke = 0;

        BigDecimal realSellTotalPrice = new BigDecimal("0");
        BigDecimal realSellTotalProfit = new BigDecimal("0");
        for (ExcelSmokeInfo smokeInfo : smokeInfos) {
//            数量
            String orderNum = smokeInfo.getOrderNum();
//            批发价
            String wholesalePrice = smokeInfo.getWholesalePrice();
//            单个商品总价
            String singlePrice = smokeInfo.getSinglePrice();
//            建议售卖价
            String suggestedSellPrice = smokeInfo.getSuggestedSellPrice();
//            合计：
//            数量合计
            totalNum += Integer.parseInt(orderNum);
//            总烟款合计
            BigDecimal bigDecimalWholesalePrice = new BigDecimal(singlePrice);
            totalAmount = totalAmount.add(bigDecimalWholesalePrice);
//            建议售卖价总价合计
            BigDecimal bigDecimalSinglePrice = new BigDecimal(suggestedSellPrice);
            estimateTotalPrice = estimateTotalPrice.add(bigDecimalSinglePrice.multiply(new BigDecimal(orderNum)));
//--
            if (smokeInfo.getIsAbnormity().equals("1")) {
                abnormalSmoke += Integer.parseInt(orderNum);
            } else {
                normalSmoke += Integer.parseInt(orderNum);
            }

            realSellTotalPrice = realSellTotalPrice.add(new BigDecimal(smokeInfo.getRealSalePriceBar()).multiply(new BigDecimal(orderNum)));
            realSellTotalProfit = realSellTotalProfit.add(new BigDecimal(smokeInfo.getBarProfit()).multiply(new BigDecimal(orderNum)));
//            --
        }
        String formattedTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
        suggestSellProfit = estimateTotalPrice.subtract(totalAmount);
        String suggestSellProfitRateFormat = new DecimalFormat("0.00%").format(suggestSellProfit.divide(estimateTotalPrice, 4, RoundingMode.HALF_UP));
        averagePrice = totalAmount.divide(new BigDecimal(totalNum), 2, BigDecimal.ROUND_HALF_UP);
        Map<String, Object> map = new HashMap<>();

        map.put("nowTime", formattedTime);
        map.put("totalNum", totalNum);
        map.put("totalAmount", totalAmount.toString());
        map.put("estimateTotalPrice", estimateTotalPrice.toString());
        map.put("suggestSellProfit", suggestSellProfit);
        map.put("suggestSellProfitRate", suggestSellProfitRateFormat);
        map.put("merchantName", StoreInfoHolder.get().getStoreName());

        map.put("averagePrice", averagePrice.toString());
        map.put("speciesQuantity", smokeInfos.size());

        map.put("normalSmoke", normalSmoke);
        map.put("abnormalSmoke", abnormalSmoke);

        map.put("realSellTotalPrice", realSellTotalPrice.toString());
        map.put("realSellTotalProfit", realSellTotalProfit.toString());
        map.put("realSellRate", new DecimalFormat("0.00%").format(realSellTotalProfit.divide(realSellTotalPrice, 4, RoundingMode.HALF_UP)));
        return map;
    }

    /**
     * 将csv文件中数据进行提取 读取到内存中
     *
     * @param baseSmokeInfos csv文件的数据
     * @return 返回转换后数据集合
     */
    @Override
    @MethodEventDescription(event = "get smoke basic info")
    public List<ExcelSmokeInfo> getBaseExcelSmokeInfo(List<CSVSmokeInfo> baseSmokeInfos) {
        //搜集csv文件订单列表中的barcode值为一个集合。
        List<ExcelSmokeInfo> smokeInfos = new ArrayList<>();
        List<String> barCodeList = baseSmokeInfos
                .stream()
                .filter(csvSmokeInfo -> Integer.parseInt(csvSmokeInfo.getOrderNum()) != 0)
                .map(CSVSmokeInfo::getBarCode)
                .collect(Collectors.toList());
        Map<String, CSVSmokeInfo> csvSmokeInfoMap = baseSmokeInfos.stream().collect(Collectors.toMap(CSVSmokeInfo::getBarCode, csvSmokeInfo -> csvSmokeInfo));
        //将数据库 查询到的数据  键为barcode。值为对象本身进行收集。
        Map<String, SmokeDto> smokeDtoBarcodeMap = smokeMapper.selectAllIsSaleSmokeByBarCode(barCodeList).stream().collect(Collectors.toMap(SmokeDto::getBarCode, smokeDto -> smokeDto));
        for (String barCode : barCodeList) {
            CSVSmokeInfo csvSmokeInfo = csvSmokeInfoMap.get(barCode);
            String orderNum = csvSmokeInfo.getOrderNum();
            SmokeDto smokeDto = smokeDtoBarcodeMap.get(barCode);
            if (smokeDto == null) {
                throw new SmokeException(csvSmokeInfo.getShoppingName() + "条码缺失,可能需要更新数据，请联系管理员", CODE.SMOKE_BAR_CODE_IN_EXIST);
            }

            ExcelSmokeInfo smokeInfo = new ExcelSmokeInfo();
            smokeInfo.setName(smokeDto.getProductName());
            smokeInfo.setWholesalePrice(new DecimalFormat("#.##").format(Double.parseDouble(smokeDto.getWholeSalePrice())));
            smokeInfo.setOrderNum(orderNum);

            smokeInfo.setSuggestedSellPrice(smokeDto.getRetailPrice());
            smokeInfo.setBarCode(barCode);

            String realSalePriceBox = smokeDto.getRealSalePriceBox();
            String realSalePriceBar = smokeDto.getRealSalePriceBar();

            //真实售价
            if (realSalePriceBox == null || realSalePriceBar == null) {
                throw new SmokeException("实际售卖价缺失：" + smokeDto.getProductName(), CODE.SMOKE_INFO_DEFICIENCY);
            }

            BigDecimal realSalePriceDec = new BigDecimal(realSalePriceBar);
            BigDecimal wholeSalePriceDec = new BigDecimal(smokeDto.getWholeSalePrice());
            realSalePriceDec = realSalePriceDec.setScale(2, RoundingMode.HALF_UP);
            wholeSalePriceDec = wholeSalePriceDec.setScale(2, RoundingMode.HALF_UP);

            //单个商品合计。
            BigDecimal orderNumDecimal = new BigDecimal(orderNum);
            smokeInfo.setSinglePrice(orderNumDecimal.multiply(wholeSalePriceDec).setScale(2, RoundingMode.HALF_UP).toString());
            //计算单条！！利润
            BigDecimal barProfit = realSalePriceDec.subtract(wholeSalePriceDec);
            //设置显示的值
            smokeInfo.setRealSalePriceBox(realSalePriceBox);
            smokeInfo.setRealSalePriceBar(realSalePriceBar);
            smokeInfo.setEarnStr(orderNum + " * " + barProfit.toString() + " = " + new BigDecimal(orderNum).multiply(barProfit).toString());
            //需要四舍五入
            smokeInfo.setRealBarRate(new DecimalFormat("0.00%").format(barProfit.divide(realSalePriceDec, 4, RoundingMode.HALF_UP)));
            //设置不显示的值
            smokeInfo.setIsAbnormity(smokeDto.getOrgIsAbnormity());
            smokeInfo.setBarProfit(barProfit.toString());
            if (smokeDto.getPicAddress() != null) {
                smokeInfo.setImgFile(FileUtil.getResourceFile(configRead.getSmokePicPath() + smokeDto.getPicAddress() + "." + smokeDto.getImageType()));
            }
            smokeInfos.add(smokeInfo);
        }

        // 合并不到一起。
        List<ExcelSmokeInfo> sortedList = smokeInfos
                .stream()
                .sorted((o1, o2) -> (int) (100 * Double.parseDouble(o1.getWholesalePrice()) - 100 * Double.parseDouble(o2.getWholesalePrice())))
                .collect(Collectors.toList());

        List<ExcelSmokeInfo> addIds = IntStream.range(0, sortedList.size())
                .mapToObj(i -> {
                    ExcelSmokeInfo smokeInfo = sortedList.get(i);
                    smokeInfo.setId(i + 1 + "");
                    return smokeInfo;
                })
                .collect(Collectors.toList());
        return addIds;
    }

    /**
     * @param listMap       其他list信息的结果集
     * @param singleInfoMap 单个数据的信息
     * @param fileBytes     模板文件，这么写是为了可以容易的选择多个模板文件
     * @return
     * @throws FileNotFoundException
     */
    public byte[] write(Map<String, Object> listMap, Map<String, Object> singleInfoMap, byte[] fileBytes) throws FileNotFoundException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        List<ExcelSmokeInfo> baseInfo = (List<ExcelSmokeInfo>) listMap.get("baseInfo");
        List<SmokeDto> addSmokeDto = (List<SmokeDto>) listMap.get("addSmokeRemarks");
        List<SmokeDto> deleteSmokeDto = (List<SmokeDto>) listMap.get("deleteSmokeRemarks");
        List<SmokeDto> updateSmokeDto = (List<SmokeDto>) listMap.get("updateSmokeRemarks");
        Map<PointXY, CellStyleWY> pointXYCellStyleWYHashMap = getExcelCellInfo(baseInfo, singleInfoMap);
        WriteSheet writeSheet = EasyExcel.writerSheet().build();
        ExportAllFileCellColorHandler exportAllFileCellColorHandler = new ExportAllFileCellColorHandler(pointXYCellStyleWYHashMap);
        exportAllFileCellColorHandler.setRows(Integer.parseInt(smokeOrderTemplate1Config.getHeadHeight()));

        ExcelWriter excelWriterBuild = EasyExcel
                .write(outputStream)
                .withTemplate(new ByteArrayInputStream(fileBytes))
                .excelType(ExcelTypeEnum.XLS)
                .registerWriteHandler(exportAllFileCellColorHandler)
                .registerWriteHandler(new MergeHandler())
                .build();
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();

        excelWriterBuild.fill(new FillWrapper("baseInfo", baseInfo), fillConfig, writeSheet);
        excelWriterBuild.fill(new FillWrapper("addSmokeDto", addSmokeDto), fillConfig, writeSheet);
        excelWriterBuild.fill(new FillWrapper("deleteSmokeDto", deleteSmokeDto), fillConfig, writeSheet);
        excelWriterBuild.fill(new FillWrapper("updateSmokeDto", updateSmokeDto), fillConfig, writeSheet);

        excelWriterBuild.fill(singleInfoMap, writeSheet);
        excelWriterBuild.finish();
        return outputStream.toByteArray();
    }

    @Override
    @MethodEventDescription(event = "use {{#2}} template generate excel", isFillMethodArg = true)
    public byte[] writeListWithListTemplate1(List<SmokeDto> smokeInfos, String templateType) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        for (int i = 0; i < smokeInfos.size(); i++) {
            smokeInfos.get(i).setId(i + 1 + "");
        }

        Map<PointXY, CellStyleWY> pointXYCellStyleWYHashMap = new HashMap<>();
        for (int i = 0; i < smokeInfos.size(); i++) {
            for (int i1 = 0; i1 < Integer.parseInt(
                    smokeListTemplate1Config.getShowColumnWidth()); i1++) {
                CellStyleWY cellStyleWY = new CellStyleWY();
                ExcelUtil.fillCellColor(cellStyleWY, i, smokeOrderTemplate1Config.getLineColorS());
                pointXYCellStyleWYHashMap.put(new PointXY(i1, i + 2), cellStyleWY);
            }
        }

        WriteSheet writeSheet = EasyExcel.writerSheet().build();
        ExcelWriter excelWriterBuild = EasyExcel
                .write(outputStream)
                .withTemplate(new ByteArrayInputStream(smokeListTemplate1Config.getTemplateFileByte()))
                .excelType(ExcelTypeEnum.XLS)
                .registerWriteHandler(new ExportAllFileCellColorHandler(pointXYCellStyleWYHashMap))
                .build();
        excelWriterBuild.fill(smokeInfos, FillConfig.builder().build(), writeSheet);
        excelWriterBuild.fill(getSmokeListMap(), writeSheet);
        excelWriterBuild.finish();
        return outputStream.toByteArray();
    }

    //查询网站最新的数据，查询smokeInfoLog 最新版本的数据，进行对比，返回不符合的数据，  没有的。

    /**
     * 返回有差距的信息  新增的，删除的，修改的，对数据的一个总结。在后端做总结分析吧，前端怪怪的。
     * 需要改进的方向还有很多，我还想知道是哪个字段进行了改进，
     *
     * @return 返回檢查結果
     */
    @Override
    public CheckInfoRes checkInfo() {
//      结果检查信息对象
        CheckInfoRes checkInfoRes = new CheckInfoRes();
//        checkInfoRes 所有的检查结果信息，前端也可以根据这个数据进行分析。
        List<CheckInfo> checkInfoList = new ArrayList<>();
//        新增的数据
        List<ProductBeanResult> addInfos = new ArrayList<>();
//        下架的数据
        List<SmokeInfoLog> deleteInfos = new ArrayList<>();
//        更新的数据
        List<CheckInfo> updateInfos = new ArrayList<>();
//        新数据的备注
        List<String> remarkList = new ArrayList<>();
//        新增和下架共同的数据合集
        List<String> addAndDeleteIds = new ArrayList<>();

        //查询  数据库信息 与 页面信息是否相同，如果不相同的话，存两个集合在
        // 网页数据
        List<ProductBeanResult> productBeanResultList = smokeInfoShanxiTobaccoCrawlerService.selectAllSmokeInfo().getRows();
        if (productBeanResultList == null || productBeanResultList.size() == 0) {
            return null;
        }
        //将原本的（） 括号给替换掉 ()
        for (ProductBeanResult productBeanResult : productBeanResultList) {
            productBeanResult.setProduct_name(StringUtils.replaceParenthesis(productBeanResult.getProduct_name()));
            productBeanResult.setShow_name(StringUtils.replaceParenthesis(productBeanResult.getShow_name()));
        }
        //对数据库查询到的数据库 数据进行map转换 将productUuid 作为key
        Map<String, SmokeInfoLog> smokeInfoLogMap = smokeInfoLogMapper.selectAllIsSaleDate().stream().collect(Collectors.toMap(SmokeInfoLog::getProductUuid, smokeInfoLog -> smokeInfoLog));
        // 比较 数据库数据和 网页的数据，判断上架，下架，修改的数据都有哪些。  两条数据根据 productUuid 进行对应  遍历的是网页数据
        for (ProductBeanResult productBeanResult : productBeanResultList) {
            String productUuid = productBeanResult.getProduct_uuid();
            SmokeInfoLog smokeInfoLog = smokeInfoLogMap.get(productUuid);
            // 进行逐条比较数据 查看查看是否 某些字段进行了修改。
            if (smokeInfoLog != null) {
                HashMap<ObjCompareFunction<Object, ProductBeanResult>, ObjCompareFunction<Object, SmokeInfoLog>> objCompareFunctionMap = new HashMap<>();
                objCompareFunctionMap.put(ProductBeanResult::getBrand_uuid, SmokeInfoLog::getBrandUuid);
                objCompareFunctionMap.put(ProductBeanResult::getFactory_uuid, SmokeInfoLog::getFactoryUuid);
                objCompareFunctionMap.put(ProductBeanResult::getOnsale, SmokeInfoLog::getOnsale);
                objCompareFunctionMap.put(ProductBeanResult::getProduct_code, SmokeInfoLog::getProductCode);
                objCompareFunctionMap.put(ProductBeanResult::getProduct_style_code, SmokeInfoLog::getProductStyleCode);
                objCompareFunctionMap.put(ProductBeanResult::getPrice_type_code, SmokeInfoLog::getPriceTypeCode);
                objCompareFunctionMap.put(ProductBeanResult::getTar_qty, SmokeInfoLog::getTarQty);
                objCompareFunctionMap.put(ProductBeanResult::getWhole_sale_price, SmokeInfoLog::getWholeSalePrice);
                objCompareFunctionMap.put(ProductBeanResult::getRetail_price, SmokeInfoLog::getRetailPrice);
                CompareRes compare = ObjComparators.compare(productBeanResult, smokeInfoLog, objCompareFunctionMap);
                //如果说比较结果是 false 说明不相等，就添加一个变更到  checkInfoList 中，然后移除这个数据，只要是能对的上就进行移除
                if (!compare.isaBoolean()) {
                    productBeanResult.setDataStatus('3');
                    CheckInfo checkInfo = new CheckInfo(smokeInfoLog, productBeanResult, compare.getDiffs());
                    checkInfoList.add(checkInfo);
                }
                //说明需要比较的都相等。 那么就认为 这一条是相等的。 在数据查到的数据进行移除这条数据
                smokeInfoLogMap.remove(productUuid);

            } else {
                //如果查询为空说明是新增的数据。
                productBeanResult.setDataStatus('1');
                checkInfoList.add(new CheckInfo(null, productBeanResult));
            }
        }
        //现在判断是否有数据没有被移除。 说明数据库有数据，但是网页没数据，这条数据已经被下架了，
        if (smokeInfoLogMap.size() != 0) {
            for (Map.Entry<String, SmokeInfoLog> smokeInfoLogEntry : smokeInfoLogMap.entrySet()) {
                SmokeInfoLog value = smokeInfoLogEntry.getValue();
                value.setDataStatus('2');
                checkInfoList.add(new CheckInfo(value, null));
            }
        }
        //分析这些数据，
        for (CheckInfo checkInfo : checkInfoList) {
            if (checkInfo.getOldInfo() == null && checkInfo.getNewInfo() != null) {
                addInfos.add(checkInfo.getNewInfo());
            }
            if (checkInfo.getOldInfo() != null && checkInfo.getNewInfo() == null) {
                deleteInfos.add(checkInfo.getOldInfo());
            }
            if (checkInfo.getOldInfo() != null && checkInfo.getNewInfo() != null) {
                updateInfos.add(checkInfo);
            }
        }
        //发现以下产品名称在“新增的产品”和“下架的产品”中同时出现：' + commonProductNames.join(', ')
        StringBuilder addAndRemarkRemark = new StringBuilder();
        // 为了打印一次  发现。。。的标志。
        boolean flag = false;
        Map<String, SmokeInfoLog> collect = deleteInfos.stream().collect(Collectors.toMap(SmokeInfoLog::getProductName, smokeInfoLog -> smokeInfoLog));

        for (ProductBeanResult addInfo : addInfos) {
            SmokeInfoLog smokeInfoLog = collect.get(addInfo.getProduct_name());
            String org_is_abnormity = addInfo.getOrg_is_abnormity();
            if (null == org_is_abnormity || org_is_abnormity.equals("")) {
                StringBuilder abnormityStr = new StringBuilder();
                abnormityStr.append(addInfo.getProduct_name() + "没有异型标志,请自行添加处理");
                remarkList.add(abnormityStr.toString());
            }
            if (smokeInfoLog != null) {
                addAndDeleteIds.add(smokeInfoLog.getProductUuid() + "_" + addInfo.getProduct_uuid());
                if (!flag) {
                    addAndRemarkRemark.append("发现以下产品名称在[新增产品]和[下架产品]中同时出现：");
                    flag = true;
                }
                addAndRemarkRemark.append(addInfo.getProduct_name()).append(" ");
            }
        }
        remarkList.add(addAndRemarkRemark.toString());

        checkInfoRes.setCheckInfos(checkInfoList);

        checkInfoRes.setAddInfos(addInfos);
        checkInfoRes.setDeleteInfos(deleteInfos);
        checkInfoRes.setUpdateInfos(updateInfos);
        checkInfoRes.setRemarks(remarkList);
        checkInfoRes.setAddAndDeleteIds(addAndDeleteIds);
        return checkInfoRes;
    }

    /**
     * 更新数据库
     * 查询放在了循环里面，不合适。
     *
     * @param checkInfoRes 之前查询的差异结果集
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CheckInfoRes updateDatabase(CheckInfoRes checkInfoRes) {
        CheckInfoRes checkInfoResLasted = smokeService.checkInfo();
        //比较最新的数据和前端传递的数据的区别，比较add delete update 里面的数据
        List<ProductBeanResult> addInfosLasted = checkInfoResLasted.getAddInfos();
        List<SmokeInfoLog> deleteInfosLasted = checkInfoResLasted.getDeleteInfos();
        List<CheckInfo> updateInfosLasted = checkInfoResLasted.getUpdateInfos();
        //---
        List<ProductBeanResult> addInfos = checkInfoRes.getAddInfos();
        List<SmokeInfoLog> deleteInfos = checkInfoRes.getDeleteInfos();
        List<CheckInfo> updateInfos = checkInfoRes.getUpdateInfos();
        //重新查询一下 传入的差距和 现在的数据是否相同，如果不相同，可能是数据又发生变化了。所以就需要重新查询差异！！
        for (int i = 0; i < addInfos.size(); i++) {
            boolean compare = ObjComparators.compare(addInfos.get(i), addInfosLasted.get(i), ProductBeanResult::getProduct_uuid);
            if (!compare) {
                return null;
            }
        }
        for (int i = 0; i < deleteInfos.size(); i++) {
            boolean compare = ObjComparators.compare(deleteInfos.get(i), deleteInfosLasted.get(i), SmokeInfoLog::getProductUuid);
            if (!compare) {
                return null;
            }
        }
        for (int i = 0; i < updateInfos.size(); i++) {
            boolean compareOld = ObjComparators.compare(updateInfos.get(i).getOldInfo(), updateInfosLasted.get(i).getOldInfo(), SmokeInfoLog::getItemUniqueIndexId);
            boolean compareNew = ObjComparators.compare(updateInfos.get(i).getNewInfo(), updateInfosLasted.get(i).getNewInfo(), ProductBeanResult::getProduct_uuid);
            if (!compareOld || !compareNew) {
                return null;
            }
        }
        Map<String, ProductBeanResult> addMap = addInfosLasted.stream().collect(Collectors.toMap(ProductBeanResult::getProduct_uuid, item -> item));
        Map<String, SmokeInfoLog> deleteMap = deleteInfosLasted.stream().collect(Collectors.toMap(SmokeInfoLog::getProductUuid, item -> item));
        Map<String, CheckInfo> updateMap = updateInfos.stream().collect(Collectors.toMap(checkInfo -> checkInfo.getOldInfo().getProductUuid(), checkInfo -> checkInfo));

        //定义操作数据库的数据
        List<Smoke> addSmokeList = new ArrayList<>();
        List<SmokeInfoLog> addSmokeInfoLogList = new ArrayList<>();


        //开始更新！！
        //1.先把在 新增和下架的部分解决掉。并且在新增和下架 集合中 删除这条数据 在smkeinfolog添加这条数据更新数据的版本 在smoke添加这条数据，
        // 更新数据的版本。首先进行删除，然后进行新增
        List<String> addAndDeleteIds = checkInfoRes.getAddAndDeleteIds();
        //这种情况只可能是在原本有，现在也有，才会出现这种情况。不可能是原本无。现在也无
//        1.1 首先进行smokeInfoLog下架的操作  之后进行smoke下架的操作
//        中间进行一个休眠几毫秒都行，避免时间一样样的
//        1.2 之后进行SmokeInfoLogs上架的操作 之后进行Smoke上架的操作。
        for (String addAndDeleteId : addAndDeleteIds) {
            String[] product_uuid = addAndDeleteId.split("_");
            //下架smokeInfoLog
            SmokeInfoLog smokeInfoLog = deleteMap.get(product_uuid[0]);
            smokeInfoLog.setId(CUtil.getUUID());
            smokeInfoLog.setCreateId(ThreadUserInfo.get().getId());
            smokeInfoLog.setCreateTime(LocalDateTime.now());
            smokeInfoLog.setVersionInfo(smokeInfoLog.getVersionInfo() + 1);
            smokeInfoLog.setDataStatus('2');
//            smokeInfoLog.setBatchSerialId();
            addSmokeInfoLogList.add(smokeInfoLog);
            //下架smoke
            String itemUniqueIndexId = smokeInfoLog.getItemUniqueIndexId();
            Smoke smoke = smokeMapper.selectOneLatestSmokeByItemId(itemUniqueIndexId);
            if (smoke == null) {
                throw new RuntimeException("查询不到产品对应的uuid");
            }
            smoke.setId(CUtil.getUUID());
            smoke.setCreateId(ThreadUserInfo.get().getId());
            smoke.setCreateTime(LocalDateTime.now());
            smoke.setVersionInfo(smoke.getVersionInfo() + 1);
            smoke.setDataStatus('2');
            addSmokeList.add(smoke);
            //上架smokeInfoLog
            ProductBeanResult productBeanResult = addMap.get(product_uuid[1]);
//            id itemId createId createTime datastatus versionInfo productUUID
            SmokeInfoLog smokeInfoLogConvert = ProductConvertSmokeInfoLog(productBeanResult);
            smokeInfoLogConvert.setId(CUtil.getUUID());
            smokeInfoLogConvert.setCreateId(ThreadUserInfo.get().getId());
            smokeInfoLogConvert.setCreateTime(LocalDateTime.now());
            smokeInfoLogConvert.setVersionInfo(smokeInfoLog.getVersionInfo() + 1);
            smokeInfoLogConvert.setItemUniqueIndexId(smokeInfoLog.getItemUniqueIndexId());
            smokeInfoLogConvert.setDataStatus('1');
            smokeInfoLogConvert.setProductUuid(productBeanResult.getProduct_uuid());
            addSmokeInfoLogList.add(smokeInfoLogConvert);
            //上架 smoke
            // 还已经修改的 未修改的 updateID updateId updateTime
            // itemId dataStatus  versionInfo createId createTime barcode realSalePriceBar  realSalePriceBox orgIsCigar
            Smoke smokeConvert = SmokeInfoLogConvertSmoke(smokeInfoLogConvert);
            smokeConvert.setId(CUtil.getUUID());
            smokeConvert.setDataStatus('1');
            smokeConvert.setCreateId(ThreadUserInfo.get().getId());
            smokeConvert.setVersionInfo(smoke.getVersionInfo() + 1);
            smokeConvert.setCreateTime(LocalDateTime.now());
            smokeConvert.setBarCode(smoke.getBarCode());
            smokeConvert.setRealSalePriceBox(smoke.getRealSalePriceBox());
            smokeConvert.setRealSalePriceBar(smoke.getRealSalePriceBar());
            smokeConvert.setOrgIsCigar(smoke.getOrgIsCigar());
            smokeConvert.setItemUniqueIndexId(smokeInfoLog.getItemUniqueIndexId());
            smokeConvert.setProductIsCorporation("1");
            addSmokeList.add(smokeConvert);
            //操作完之后在 map中移除 数据
            addMap.remove(product_uuid[1]);
            deleteMap.remove(product_uuid[0]);
        }
        //2.再解决新增， 可能上架的这个是之前存在的。之前下架过！！！但是现在又上架了，通过名字查询，名字查不到的话进行正常的新增。
        // 这事闹得，只能根据名字来修改。
        for (Map.Entry<String, ProductBeanResult> entry : addMap.entrySet()) {

            //在 smokeInfo新增。在smoke新增
            //id itemId createId createTime datastatus versionInfo
            SmokeInfoLog smokeInfoLog = ProductConvertSmokeInfoLog(entry.getValue());
            SmokeInfoLog smokeInfoLogDatabase = smokeInfoLogMapper.selectOneLatestSmokeByProductName(smokeInfoLog.getProductName());
            boolean databaseExistFlag = false;
            if (smokeInfoLogDatabase != null) {
                //如果不为空说明数据库原本存在这条数据，  如果状态为2，说明正常，层架下架了，现在如果不为2，说明不正常
                if (smokeInfoLogDatabase.getDataStatus() != '2') {
                    throw new RuntimeException("为什么新增的数据之前在数据库没下架" + smokeInfoLog.toString());
                }
                //如果等于2，说明已经下架了，现在进行新增的话需要沿用之前的id
                databaseExistFlag = true;
            }
            smokeInfoLog.setId(CUtil.getUUID());
            smokeInfoLog.setCreateId(ThreadUserInfo.get().getId());
            smokeInfoLog.setCreateTime(LocalDateTime.now());
            smokeInfoLog.setDataStatus('1');
            smokeInfoLog.setProductUuid(entry.getValue().getProduct_uuid());
            if (databaseExistFlag) {
                smokeInfoLog.setItemUniqueIndexId(smokeInfoLogDatabase.getItemUniqueIndexId());
                smokeInfoLog.setVersionInfo(smokeInfoLogDatabase.getVersionInfo() + 1);
            } else {
                smokeInfoLog.setVersionInfo(1);
                smokeInfoLog.setItemUniqueIndexId(CUtil.getUUID());
            }
            addSmokeInfoLogList.add(smokeInfoLog);
            //  在smoke新增
            //  realSalePriceBar  realSalePriceBox  这俩得自己填   barcode  orgIsCigar 这俩可以查 TODO：
            //  itemId dataStatus pro_is_corporation versionInfo createId createTime updateID updateId updateTime
            Smoke smoke = SmokeInfoLogConvertSmoke(smokeInfoLog);
            if (databaseExistFlag) {
                Smoke smoke1 = smokeMapper.selectOneLatestSmokeByProductName(smoke.getProductName());
                if (smoke1 != null) {
                    smoke.setVersionInfo(smoke1.getVersionInfo() + 1);
                    smoke.setItemUniqueIndexId(smoke1.getItemUniqueIndexId());
                    smoke.setBarCode(smoke1.getBarCode());
                    smoke.setRealSalePriceBox(smoke1.getRealSalePriceBox());
                    smoke.setRealSalePriceBar(smoke1.getRealSalePriceBar());
                    smoke.setOrgIsCigar(smoke1.getOrgIsCigar());
                } else {
                    throw new RuntimeException("有问题" + smoke.getProductName() + "数据为什么在smoke表不存在");
                }
            } else {
                smoke.setVersionInfo(1);
                smoke.setItemUniqueIndexId(smokeInfoLog.getItemUniqueIndexId());
            }
            smoke.setId(CUtil.getUUID());
            smoke.setProductUuid(smokeInfoLog.getProductUuid());
            smoke.setDataStatus('1');
            smoke.setProductIsCorporation("1");
            smoke.setCreateId(ThreadUserInfo.get().getId());
            smoke.setCreateTime(LocalDateTime.now());
            addSmokeList.add(smoke);
        }
        //3.在解决下架 。直接查询出来下架吧
        for (Map.Entry<String, SmokeInfoLog> smokeInfoLogEntry : deleteMap.entrySet()) {
            //两个都下架  smokeInfoLog  和 smoke都下架
            SmokeInfoLog smokeInfoLog = smokeInfoLogEntry.getValue();
            smokeInfoLog.setId(CUtil.getUUID());
            smokeInfoLog.setVersionInfo(smokeInfoLog.getVersionInfo() + 1);
            smokeInfoLog.setDataStatus('2');
            smokeInfoLog.setCreateTime(LocalDateTime.now());
            smokeInfoLog.setCreateId(ThreadUserInfo.get().getId());
            addSmokeInfoLogList.add(smokeInfoLog);
            String itemUniqueIndexId = smokeInfoLog.getItemUniqueIndexId();
            Smoke smoke = smokeMapper.selectOneLatestSmokeByItemId(itemUniqueIndexId);
            smoke.setDataStatus('2');
            smoke.setId(CUtil.getUUID());
            smoke.setVersionInfo(smoke.getVersionInfo() + 1);
            smoke.setCreateTime(LocalDateTime.now());
            smoke.setCreateId(ThreadUserInfo.get().getId());
            smoke.setProductIsCorporation("1");
            smoke.setUpdateId(null);
            smoke.setUpdateTime(null);
            addSmokeList.add(smoke);
        }
        //4.解决更新
        //需要更新两个地方。smoke 表和smokeInfoLog表。 需要之前的数据。
        for (Map.Entry<String, CheckInfo> checkInfoEntry : updateMap.entrySet()) {
            CheckInfo checkInfo = checkInfoEntry.getValue();
            ProductBeanResult productBeanResultNewInfo = checkInfo.getNewInfo();
            SmokeInfoLog smokeInfoLogOldInfo = checkInfo.getOldInfo();
            SmokeInfoLog smokeInfoLog = ProductConvertSmokeInfoLog(productBeanResultNewInfo);
            //缺少 id itemId uuid createId createTime datastatus versionInfo
            smokeInfoLog.setId(CUtil.getUUID());
            smokeInfoLog.setItemUniqueIndexId(smokeInfoLogOldInfo.getItemUniqueIndexId());
            smokeInfoLog.setProductUuid(smokeInfoLogOldInfo.getProductUuid());
            smokeInfoLog.setDataStatus('3');
            smokeInfoLog.setVersionInfo(smokeInfoLogOldInfo.getVersionInfo() + 1);
            smokeInfoLog.setCreateId(ThreadUserInfo.get().getId());
            smokeInfoLog.setCreateTime(LocalDateTime.now());
            addSmokeInfoLogList.add(smokeInfoLog);
            //添加更新smoke的数据
            //判断是否需要更新 smoke
            Smoke smoke = smokeMapper.selectOneLatestSmokeByItemId(smokeInfoLogOldInfo.getItemUniqueIndexId());
            HashMap<ObjCompareFunction<Object, Smoke>, ObjCompareFunction<Object, SmokeInfoLog>> compareSmokeSmokeInfoLogFields = new HashMap<>();
            compareSmokeSmokeInfoLogFields.put(Smoke::getProductName, SmokeInfoLog::getProductName);
            //这条数据 应该说不会 不相等，因为就是根据这条数据来的，
            compareSmokeSmokeInfoLogFields.put(Smoke::getProductUuid, SmokeInfoLog::getProductUuid);
            compareSmokeSmokeInfoLogFields.put(Smoke::getProductCode, SmokeInfoLog::getProductCode);
            compareSmokeSmokeInfoLogFields.put(Smoke::getBrandUuid, SmokeInfoLog::getBrandUuid);
            compareSmokeSmokeInfoLogFields.put(Smoke::getFactorySimpleName, SmokeInfoLog::getFactorySimpleName);
            compareSmokeSmokeInfoLogFields.put(Smoke::getWholeSalePrice, SmokeInfoLog::getWholeSalePrice);
            compareSmokeSmokeInfoLogFields.put(Smoke::getRetailPrice, SmokeInfoLog::getRetailPrice);
            compareSmokeSmokeInfoLogFields.put(Smoke::getOrgIsAbnormity, SmokeInfoLog::getOrgIsAbnormity);
            compareSmokeSmokeInfoLogFields.put(Smoke::getPriceTypeCode, SmokeInfoLog::getPriceTypeCode);
            compareSmokeSmokeInfoLogFields.put(Smoke::getPriceTypeCode, SmokeInfoLog::getPriceTypeCodename);
            CompareRes compare = ObjComparators.compare(smoke, smokeInfoLog, compareSmokeSmokeInfoLogFields);
            //如果不需要更新就不更新。继续下一条数据
            if (!compare.isaBoolean()) {
                continue;
            }
            //进行更新
            Smoke smokeConvert = SmokeInfoLogConvertSmoke(smokeInfoLog);
            // 已添加：itemID dataStatus pro_is_corporation versionInfo orgIsCigar  createId createTime barcode realSalePriceBar realSalePriceBox
            // 未添加： updateID updateId updateTime
            smokeConvert.setId(CUtil.getUUID());
            smokeConvert.setDataStatus('3');
            smokeConvert.setProductIsCorporation("1");
            smokeConvert.setVersionInfo(smoke.getVersionInfo() + 1);
            smokeConvert.setOrgIsCigar(smoke.getOrgIsCigar());
            smokeConvert.setCreateId(ThreadUserInfo.get().getId());
            smokeConvert.setCreateTime(LocalDateTime.now());
            smokeConvert.setBarCode(smoke.getBarCode());
            smokeConvert.setRealSalePriceBar(smoke.getRealSalePriceBar());
            smokeConvert.setRealSalePriceBox(smoke.getRealSalePriceBox());
            addSmokeList.add(smokeConvert);
        }
        String latestSerialId = smokeMapper.getLatestSerialId();
        String serialId = getSerialId(latestSerialId, checkInfoResLasted.getCheckInfos().size());

        addSmokeList.forEach(smoke -> smoke.setBatchSerialId(serialId));
        addSmokeInfoLogList.forEach(smokeInfoLog -> smokeInfoLog.setBatchSerialId(serialId));

        smokeInfoLogService.saveBatch(addSmokeInfoLogList);
        smokeService.saveBatch(addSmokeList);
        return checkInfoRes;
    }

    /**
     * 更新 更新数据的时候没有被更新的数据。
     * 有是否为雪茄  还有其中的条码  各个烟的图片
     * 可能这个接口订烟的时候才开放，不过可以大概写写
     */
    @Override
    public Map<String, List<Smoke>> updateOtherData() {
        OrderingInformation orderingInformation = smokeInfoShanxiTobaccoCrawlerService.selectAvailableAmount();
        List<ProdLimitInfos> prod_limit_infos = orderingInformation.getProd_limit_infos();
        Map<String, Smoke> smokeMap = smokeMapper.selectAllIsSaleSmoke().stream().collect(Collectors.toMap(Smoke::getProductUuid, smoke -> smoke));
        List<Smoke> originalSmokes = new ArrayList<>();
        List<Smoke> updatedSmokes = new ArrayList<>();
        for (ProdLimitInfos prod_limit_info : prod_limit_infos) {
            String product_uuid = prod_limit_info.getProduct_uuid();
            Smoke smoke = smokeMap.get(product_uuid);
            if (smoke == null) {
                throw new SmokeException("数据有问题，请联系管理员", CODE.SMOKE_fail1);
            }
            String barCode = smoke.getBarCode();
            String bar_code2 = prod_limit_info.getBar_code2();
            String is_cigar = prod_limit_info.getIs_cigar();
            String orgIsCigar = smoke.getOrgIsCigar();
            if (!bar_code2.equals(barCode) || !is_cigar.equals(orgIsCigar)) {
                Smoke originalSmoke = new Smoke();
                BeanUtils.copyProperties(smoke, originalSmoke);
                originalSmokes.add(originalSmoke);
                smoke.setBarCode(bar_code2);
                smoke.setOrgIsCigar(is_cigar);
                smoke.setCreateId(ThreadUserInfo.get().getId());
                smoke.setCreateTime(LocalDateTime.now());
                smoke.setId(CUtil.getUUID());
                smoke.setVersionInfo(smoke.getVersionInfo() + 1);
                updatedSmokes.add(smoke);
            }
        }
        boolean b = smokeService.saveBatch(updatedSmokes);
        Map<String, List<Smoke>> resMaps = new HashMap<>();
        resMaps.put("originalSmokes", originalSmokes);
        resMaps.put("updatedSmokes", updatedSmokes);
        if (b) {
            return resMaps;
        } else {
            throw new SmokeException("更新雪茄、barCode 失败", CODE.SMOKE_UPDATE_FAIL);
        }
    }

    /**
     * 下载缺失的图片
     *
     * @return
     */
    //smokeinfolog 表和 pic表连表查出没有下载的图片信息。  进行一个 下载。在数据库添加这条数据
    @Override
    public Map<String, List<String>> downDeficiencyPic() {
        Map<String, List<String>> resMap = new HashMap<>();
        //查询没有被下载的图片
        List<SmokeInfoLog> smokeInfoLogs = smokeInfoLogMapper.selectQueryImagesNotBeenDownloaded();
        //保存 时间 pic的集合
        List<Pic> pics = new ArrayList<>();
        List<String> downSuccessList = new ArrayList<>();
        List<String> downFailList = new ArrayList<>();
        //下载
        for (SmokeInfoLog smokeInfoLog : smokeInfoLogs) {
            String imgMain = smokeInfoLog.getImgMain();
            byte[] bytes = smokeInfoShanxiTobaccoCrawlerService.downHttpPic(imgMain);
            ByteArrayInputStream bis = new ByteArrayInputStream(bytes);
            BufferedImage image = null;
            try {
                image = ImageIO.read(bis);
            } catch (IOException e) {
                throw new PicNullException();
            }
            if (image != null) {
                Pic pic = new Pic();
                pic.setId(CUtil.getUUID());
                pic.setCreateId("111");
                pic.setObjId(smokeInfoLog.getItemUniqueIndexId());
                pic.setImageType("jpg");
                String addressUuid = CUtil.getUUID();
                pic.setPicAddress(addressUuid);
                pic.setCreateTime(LocalDateTime.now());
                pics.add(pic);
                downSuccessList.add(smokeInfoLog.getProductName());
                // 保存图片到本地文件
                try {
                    ImageIO.write(image, "jpg", new File("src\\main\\resources\\smokePic\\" + addressUuid + ".jpg"));
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                downFailList.add(smokeInfoLog.getProductName());
            }
            try {
                bis.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        resMap.put("success", downSuccessList);
        resMap.put("fail", downFailList);
        if (picService.saveBatch(pics)) {
            return resMap;
        } else {
            return null;
        }
    }

    //查询数据库卷烟的差异。
    @Override
    public Map<String, List<SmokeNews>> queryLatelyAlertSmoke() {
        Map<String, List<SmokeNews>> changeMap = new HashMap<>();
        List<String> updateIds = new ArrayList<>();
        List<SmokeNews> addSmokeNews = new ArrayList<>();
        List<SmokeNews> deleteSmokeNews = new ArrayList<>();
        List<SmokeNews> updateSmokeNews = new ArrayList<>();
        List<Smoke> smokes = smokeMapper.queryLatelyAlertSmoke();
        for (Smoke smoke : smokes) {
            char dataStatus = smoke.getDataStatus();
            if (dataStatus == 1) {
                //上架
                SmokeDto smokeDto = new SmokeDto();
                BeanUtils.copyProperties(smoke, smokeDto);
                SmokeNews smokeNews = new SmokeNews();
                smokeNews.setSmokeDtoNew(smokeDto);
                addSmokeNews.add(smokeNews);
            } else if (dataStatus == 2) {
                //下架
                SmokeDto smokeDto = new SmokeDto();
                BeanUtils.copyProperties(smoke, smokeDto);
                SmokeNews smokeNews = new SmokeNews();
                smokeNews.setSmokeDtoOld(smokeDto);
                deleteSmokeNews.add(smokeNews);
            } else if (dataStatus == 3) {
                //在查一下之前 的版本，根据item_id
                updateIds.add(smoke.getItemUniqueIndexId());
            } else {
                throw new RuntimeException("一条数据怎么能没状态呢？");
            }
        }

//TODO:  查询的时候 有一个id不够，还需要一个版本号儿。当前版本-1、  上面查询烟的方式也不对， 会漏掉很多 本来就是新增的烟！！ 怎么做，当修改的时候加一个批次号。
// 看来得重新更新了，更新完之后看一下  那三个新增和下架的id对不对。。

        changeMap.put("addSmoke", addSmokeNews);
        changeMap.put("deleteSmoke", deleteSmokeNews);
        changeMap.put("update", updateSmokeNews);
        return changeMap;
    }

    /**
     * 传入查询到的数据，填到 excel 返回字节byte
     * 两种模板填写数据的方式不一样  需要的数据是两套数据  所以就会有两个方法 进行填充
     */
    @Override
    @MethodEventDescription(event = "use {{#2}} template generate excel", isFillMethodArg = true)
    public byte[] writeListWithListTemplate2(List<SmokeDto> smokeInfos, String templateFileName) {
//        判断是模板2还是模板2_1  根据不同的模板 赋值
        ByteArrayInputStream listTemplateByteArrayInputStream;
        int listTemplateShowColumnWidth;
        if (templateFileName.contains("2_1")) {
            listTemplateByteArrayInputStream = new ByteArrayInputStream(
                    smokeListTemplate2_1Config.getTemplateFileByte());
            listTemplateShowColumnWidth = Integer.parseInt(
                    smokeListTemplate2_1Config.getShowColumnWidth());
        } else {
            listTemplateByteArrayInputStream = new ByteArrayInputStream(
                    smokeListTemplate2Config.getTemplateFileByte());
            listTemplateShowColumnWidth = Integer.parseInt(
                    smokeListTemplate2Config.getShowColumnWidth());
        }

        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        List<SmokeDto> generalSmokes = new ArrayList<>();
        List<SmokeDto> abnormitySmokes = new ArrayList<>();
        for (int i = 0; i < smokeInfos.size(); i++) {
            SmokeDto smoke = smokeInfos.get(i);
            if (smoke.getOrgIsAbnormity().equals("是")) {
                int size = abnormitySmokes.size();
                smoke.setId(size + 1 + "");
                smoke.setPicFile(smoke.getPicFile());
                abnormitySmokes.add(smoke);
            } else {
                int size = generalSmokes.size();
                smoke.setId(size + 1 + "");
                smoke.setPicFile(smoke.getPicFile());
                generalSmokes.add(smoke);
            }
        }
        int generalSize = generalSmokes.size();

        // 为常规的烟部分添加颜色 集合
        Map<PointXY, CellStyleWY> pointXYCellStyleWYHashMap = new HashMap<>();
        for (int i = 0; i < generalSmokes.size(); i++) {
            for (int i1 = 0; i1 < listTemplateShowColumnWidth; i1++) {
                CellStyleWY cellStyleWY = new CellStyleWY();
                ExcelUtil.fillCellColor(cellStyleWY, i, smokeListTemplate1Config.getLineColorS());
                pointXYCellStyleWYHashMap.put(new PointXY(i1, i + 2), cellStyleWY);
            }
        }

        HashMap<Integer, List<Integer>> fillColorMap = new HashMap<>();
        for (int i = 0; i < abnormitySmokes.size(); i++) {
            Smoke smoke = abnormitySmokes.get(i);
            if (smoke.getOrgIsCigar().equals("是")) {
                fillColorMap.put(i + 3 + generalSize, CUtil.getNumberList(listTemplateShowColumnWidth));
            }
        }
        ExportAllFileCellColorHandler exportAllFileCellColorHandler = new ExportAllFileCellColorHandler(pointXYCellStyleWYHashMap);
        exportAllFileCellColorHandler.setRows(Integer.parseInt(smokeListTemplate2Config.getFirstHeadHeight()));

        ExportAllFileCellColorHandler2 exportAllFileCellColorHandler2 = new ExportAllFileCellColorHandler2(fillColorMap, IndexedColors.LIGHT_TURQUOISE1.getIndex());
        exportAllFileCellColorHandler2.setRows(Integer.parseInt(
                smokeListTemplate2Config.getSecondHeadHeight()) + Integer.parseInt(
                smokeListTemplate2Config.getFirstHeadHeight()) + generalSize);
        ExcelWriter excelWriterBuild = EasyExcel
                .write(outputStream)
                .withTemplate(listTemplateByteArrayInputStream)
                .excelType(ExcelTypeEnum.XLS)
                .registerWriteHandler(exportAllFileCellColorHandler)
                .registerWriteHandler(exportAllFileCellColorHandler2)
                .build();
        FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
        WriteSheet build = EasyExcel.writerSheet().build();
        excelWriterBuild.fill(new FillWrapper("general", generalSmokes), fillConfig, build);
        excelWriterBuild.fill(new FillWrapper("abnormity", abnormitySmokes), fillConfig, build);
        excelWriterBuild.fill(getSmokeListMap(), build);
        excelWriterBuild.finish();
        return outputStream.toByteArray();
    }


    @Override
    @MethodEventDescription(event = "excelToPic", isShowAllArg = true)
    public byte[] excelToPic(byte[] excelByte) {
        ByteArrayOutputStream byteArrayOutputStream = null;
        try {
            byteArrayOutputStream = FileUtil.excel2Pic(new ByteArrayInputStream(excelByte));
        } catch (IOException e) {
            e.printStackTrace();
        }
        return byteArrayOutputStream.toByteArray();
    }

    /**
     * 根据现有的信息返回一个 表格样式map 每个单元格是什么样式
     *
     * @param smokeInfos
     * @param map
     * @return
     */
    private Map<PointXY, CellStyleWY> getExcelCellInfo(List<ExcelSmokeInfo> smokeInfos, Map<String, Object> map) {
        Map<PointXY, CellStyleWY> pointXYCellStyleWYHashMap = new HashMap<>();

        //遍历每一行数据信息颜色的填充
        for (int i = 0; i < smokeInfos.size(); i++) {
            //便利这一行的每一个元素
            for (int j = 0; j < Integer.parseInt(
                    smokeOrderTemplate1Config.getWidthOfColumn()); j++) {
                CellStyleWY cellStyleWY = new CellStyleWY();
                //设置 每一行首个单元格的颜色
                if (j == 0 && "1".equals(smokeInfos.get(i).getIsAbnormity())) {
                    //如果 这个烟是异型，设置红色
                    cellStyleWY.setColorIndex(IndexedColors.RED.getIndex());
                    cellStyleWY.setCellType('0');
                } else {
                    //设置每个单元格的类型，图片或者文本
                    if (j + 1 == Integer.parseInt(
                            smokeOrderTemplate1Config.getImgColumnPosition())) {
                        cellStyleWY.setCellType('1');
                        continue;
                    } else {
                        cellStyleWY.setCellType('0');
                        if (StringUtils.containsNumber(smokeOrderTemplate1Config.getRenderColorColumn(), j + 1)) {
                            ExcelUtil.fillCellColor(cellStyleWY, i, smokeOrderTemplate1Config.getLineColorS());
                        }
                    }
                }
                pointXYCellStyleWYHashMap.put(new PointXY(j, i + 3), cellStyleWY);
            }
        }
        return pointXYCellStyleWYHashMap;
    }

    /**
     * 得到 smokelist 的map数据
     *
     * @return
     */
    public Map<String, String> getSmokeListMap() {
        HashMap<String, String> stringStringHashMap = new HashMap<>();
        stringStringHashMap.put("nowTime", DateUtil.queryCurrentDay());
        return stringStringHashMap;
    }

    /**
     * 将 productBeanResult 属性转换到  SmokeInfoLog 中
     * <p>
     * smokeLog中缺少 id itemId productUuid createId createTime datastatus versionInfo
     *
     * @param productBeanResult
     * @return
     */
    public SmokeInfoLog ProductConvertSmokeInfoLog(ProductBeanResult productBeanResult) {
        SmokeInfoLog smokeInfoLog = new SmokeInfoLog();
        smokeInfoLog.setBrandCulture(productBeanResult.getBrand_culture());
        smokeInfoLog.setBrandName(productBeanResult.getBrand_name());
        smokeInfoLog.setBrandUuid(productBeanResult.getBrand_uuid());
        smokeInfoLog.setFactorySimpleName(productBeanResult.getFactory_simple_name());
        smokeInfoLog.setFactoryUuid(productBeanResult.getFactory_uuid());
        smokeInfoLog.setFeature(productBeanResult.getFeature());
        smokeInfoLog.setFlavour(productBeanResult.getFlavour());
        smokeInfoLog.setImgBack(productBeanResult.getImg_back());
        smokeInfoLog.setImgBottom(productBeanResult.getImg_bottom());
        smokeInfoLog.setImgCigarette(productBeanResult.getImg_cigarette());
        smokeInfoLog.setImgElevation(productBeanResult.getImg_elevation());
        smokeInfoLog.setImgFront(productBeanResult.getImg_front());
        smokeInfoLog.setImgLeft(productBeanResult.getImg_left());
        smokeInfoLog.setImgMain(productBeanResult.getImg_main());
        smokeInfoLog.setImgRight(productBeanResult.getImg_right());
        smokeInfoLog.setImgTop(productBeanResult.getImg_top());

        smokeInfoLog.setIsIntake(productBeanResult.getIs_intake());
        smokeInfoLog.setManageUnitUuid(productBeanResult.getManage_unit_uuid());
        smokeInfoLog.setOffTime(productBeanResult.getOff_time());
        smokeInfoLog.setOnsale(productBeanResult.getOnsale());
        smokeInfoLog.setOrgIsAbnormity(productBeanResult.getOrg_is_abnormity());
        smokeInfoLog.setPacking(productBeanResult.getPacking());
        smokeInfoLog.setPhotoFid(productBeanResult.getPhoto_fid());
        smokeInfoLog.setPriceTypeCode(productBeanResult.getPrice_type_code());
        smokeInfoLog.setPriceTypeCodename(productBeanResult.getPrice_type_codename());
        smokeInfoLog.setProductCode(productBeanResult.getProduct_code());
        smokeInfoLog.setProductCodeOrder(productBeanResult.getProduct_code_order());
        smokeInfoLog.setProductName(productBeanResult.getProduct_name());
        smokeInfoLog.setProductStyleCode(productBeanResult.getProduct_style_code());
        smokeInfoLog.setProductTypeCode(productBeanResult.getProduct_type_code());
        smokeInfoLog.setRemark(productBeanResult.getRemark());
        smokeInfoLog.setRetailPrice(productBeanResult.getRetail_price());
        smokeInfoLog.setShowName(productBeanResult.getShow_name());
        smokeInfoLog.setShowTag1(productBeanResult.getShow_tag1());
        smokeInfoLog.setShowTag2(productBeanResult.getShow_tag2());
        smokeInfoLog.setShowTag3(productBeanResult.getShow_tag3());
        smokeInfoLog.setSlogan(productBeanResult.getSlogan());
        smokeInfoLog.setSupplyFully(productBeanResult.getSupply_fully());
        smokeInfoLog.setTarQty(productBeanResult.getTar_qty());
        smokeInfoLog.setWholeSalePrice(productBeanResult.getWhole_sale_price());
        smokeInfoLog.setExtUuid(productBeanResult.getExt_uuid());
        smokeInfoLog.setOnTime(productBeanResult.getOn_time());
        smokeInfoLog.setPosition(productBeanResult.getPosition());
        smokeInfoLog.setProductTypeCodename(productBeanResult.getProduct_type_codename());
        return smokeInfoLog;
    }

    /**
     * smokeInfoLog 到Smoke的转换
     * 没有 id itemID productUUId barcode realSalePriceBar  realSalePriceBox orgIsCigar dataStatus pro_is_corporation versionInfo createId createTime updateID updateId updateTime
     *
     * @param smokeInfoLog
     * @return
     */
    public Smoke SmokeInfoLogConvertSmoke(SmokeInfoLog smokeInfoLog) {
        Smoke smoke = new Smoke();
        smoke.setProductName(smokeInfoLog.getProductName());
        smoke.setProductUuid(smokeInfoLog.getProductUuid());
        smoke.setBrandName(smokeInfoLog.getBrandName());
        smoke.setBrandUuid(smokeInfoLog.getBrandUuid());
        smoke.setProductCode(smokeInfoLog.getProductCode());
        smoke.setFactorySimpleName(smokeInfoLog.getFactorySimpleName());
        smoke.setWholeSalePrice(smokeInfoLog.getWholeSalePrice());
        smoke.setRetailPrice(smokeInfoLog.getRetailPrice());
        smoke.setOrgIsAbnormity(smokeInfoLog.getOrgIsAbnormity());
        smoke.setPriceTypeCodeName(smokeInfoLog.getPriceTypeCodename());
        smoke.setPriceTypeCode(smokeInfoLog.getPriceTypeCode());
        smoke.setProductIsSale(smokeInfoLog.getOnsale());
        smoke.setProductIsCorporation("1");
        return smoke;
    }

    /**
     * 得到序列号 批次数量
     */
    /**
     * @param maxSerialId          查询到之前的最大批次号
     * @param currentBatchQuantity 当前批次的数量
     * @return
     */
    public String getSerialId(String maxSerialId, int currentBatchQuantity) {
        if (currentBatchQuantity <= 0 || currentBatchQuantity > 100000000) {
            throw new RuntimeException("批次数量过多，大概率是被攻击了");
        }
        String currentDate = new SimpleDateFormat("yyyyMMdd").format(new Date());
        StringBuilder stringBuilder = new StringBuilder(currentDate);
        if (maxSerialId == null || !maxSerialId.startsWith(currentDate)) {
            stringBuilder.append("0001");
        } else {
            int batchNumber = Integer.parseInt(maxSerialId.substring(8, 12)) + 1;
            stringBuilder.append(String.format("%04d", batchNumber));
        }

        stringBuilder.append(ThreadUserInfo.get().getId().equals("111") ? "8888" : "9999");
        stringBuilder.append(String.format("%08d", currentBatchQuantity));
        stringBuilder.append(CUtil.getUUID(), 0, 8);
        return stringBuilder.toString();
    }

    //   修改得到的数据，进行一个阉割。这个阉割不需要监听器去阉割，而是后续的手段进行阉割  修正数据
    private void revisedData(WeeklySupplyStrategyData weeklySupplyStrategyData) {
        // 移除 gearPutList 中不需要的元素
        weeklySupplyStrategyData.getGearSelection().getList().removeIf(item -> !item.getReleaseOrNo().equals("是"));

        // 使用迭代器移除 gearExtendSelectionList 中不需要的元素
        Iterator<GearExtendSelection> gearExtendSelectionIterator = weeklySupplyStrategyData.getGearExtendSelectionList().iterator();
        while (gearExtendSelectionIterator.hasNext()) {
            GearExtendSelection gearExtendSelection = gearExtendSelectionIterator.next();
            List<AnticipatedOrderData> list = gearExtendSelection.getList();
            if (list != null) {
                list.removeIf(anticipatedOrderData -> !anticipatedOrderData.getReleaseOrNo().equals("是"));
                // 如果列表为空，则移除 gearExtendSelection
                if (list.isEmpty()) {
                    gearExtendSelectionIterator.remove();
                }
            }
        }
    }
}